import customtkinter
from tkinter import ttk


class Gui_Option:
    '''
    gui类，用于创建基本的图形化界面
    '''

    def __init__(self):
        '''
        需求配置
        '''
        # 设置主题:"blue" (default), "green", "dark-blue"
        self.theme = 'green'
        customtkinter.set_default_color_theme(self.theme)

        # 设置外观模式:"system" (default),"dark","light"
        self.appearance_mode = 'system'
        customtkinter.set_appearance_mode(self.appearance_mode)

        # 设置gui的宽度
        self.gui_width = 500

        # 设置gui的高度
        self.gui_height = 500

        # 设置gui的坐标，1.6为最大，0.5为中间
        self.gui_x = 0.5
        self.gui_y = 0.5

        # 窗口前景色
        self.pro_fg_color = None

        # 生成主窗口
        self.root = customtkinter.CTk(fg_color=self.pro_fg_color)

        # 窗口标题
        self.root.wm_title('芜湖')

        # 定位窗口和设置窗口大小
        self.gui_geometry(self.root, self.gui_width, self.gui_height, self.gui_x, self.gui_y)

        # 设置窗口最小大小
        self.root.minsize(int(self.gui_width * 0.8), int(self.gui_height * 0.8))

        # 设置窗口大小是否允许修改bool(default)
        self.root.resizable(True, True)

        # 设置窗口状态 （'normal'， 'iconic'， 'withdrawn'， 'zoomed'），如果未传递参数，则返回当前状态。
        # self.root.wm_state('normal')
        '''美化treeview'''
        # 创建 Style 对象
        style = ttk.Style()

        # 配置 Treeview 整体样式
        style.configure("Treeview",
                        background="#f0f0f0",  # 背景色
                        foreground="black",  # 前景色（文字颜色）
                        rowheight=25,  # 行高
                        fieldbackground="#f0f0f0",  # 单元格背景色
                        )

        # 配置 Treeview 表头样式
        '''
        relief
        组件边框的样式，可选值有 
        'flat'（平的，无明显边框）、
        'raised'（凸起效果）、
        'sunken'（凹陷效果）、
        'ridge'（脊状边框）、
        'groove'（槽状边框）等。
        '''
        style.configure("Treeview.Heading",
                        background="#d3d3d3",  # 表头背景色
                        foreground="black",  # 表头文字颜色
                        relief="ridge",  # 表头边框样式
                        font=("幼圆", 12, "bold"),
                        )

        # 配置选中项样式
        style.map('Treeview',
                  background=[('selected', '#a6c9e2')])  # 选中项背景色

    # 窗口位置和大小设置
    def gui_geometry(self, master, w_w: int, h_h: int, x_x: float, y_y: float):
        '''
        设置gui窗口的宽度、高度，出现的坐标
        :return:
        '''
        # 检测屏幕的大小
        sc_width = self.root.winfo_screenwidth()
        sc_height = self.root.winfo_screenheight()

        # 计算窗口的大小
        gui_x = int((sc_width - w_w) * x_x)
        gui_y = int((sc_height - h_h) * y_y)

        # 设置窗口大小
        master.geometry(f'{w_w}x{h_h}+{gui_x}+{gui_y}')
        return

    # 创建变量对象
    def create_var(self, master, mode, value):
        '''
        创造Var变量，与父组件绑定
        :param master: 父组件对象
        :param mode: 1=int,2=float,3=bool,其他=str
        :param value: 对应的值
        :return: Var对象
        '''
        if mode == 1:
            # int
            return customtkinter.IntVar(master, value)
        elif mode == 2:
            # float
            return customtkinter.DoubleVar(master, value)
        elif mode == 3:
            # bool
            return customtkinter.BooleanVar(master, value)
        else:
            # str
            return customtkinter.StringVar(master, value)

    # 子窗口
    def toplevel_widget(self, master, title: str, w_w: int, h_h: int, x_x: float, y_y: float):
        '''
        子窗口
        :param master: 根
        :param title: 子窗口的标题
        :param w_w: 子窗口的宽度，必须是整数
        :param h_h: 子窗口的高度，必须是整数
        :param x_x: 子窗口的x坐标，必须是2以内小数，0.5为居中
        :param y_y: 子窗口的y坐标，必须是2以内小数，0.5为居中
        :return: 子窗口对象
        '''
        top_ = customtkinter.CTkToplevel(master)
        # 设置子窗口标题
        top_.wm_title(title)
        # 设置子窗口不能被改变窗口大小
        top_.resizable(False, False)
        # 设置子窗口的大小和位置
        self.gui_geometry(top_, w_w, h_h, x_x, y_y)
        '''
        top_.deiconify()
        top_.focus_get()

        def on_toplevel_close():
            master.deiconify()

        # 绑定 Toplevel 窗口的关闭事件
        top_.protocol("WM_DELETE_WINDOW", on_toplevel_close)
        '''
        return top_

    # 标签组件
    def label_widget(self, master, variable):
        '''
        标签组件
        :param master: 父组件
        :param variable: 绑定的数据变量
        :return: 标签组件对象
        '''
        return customtkinter.CTkLabel(master, textvariable=variable)

    # 按钮组件
    def button_widget(self, master, variable):
        '''
        按钮组件
        :param master: 父组件
        :param variable: 绑定的数据变量
        :return: 按钮组件对象
        '''
        return customtkinter.CTkButton(master, textvariable=variable)

    # 文本框组件
    def text_box_widget(self, master):
        '''
        文本框组件
        :param master: 父组件
        :return: 文本框组件对象
        '''
        return customtkinter.CTkTextbox(master)

    # 输入框组件
    def entry_widget(self, master, variable):
        '''
        输入框组件
        :param master: 父组件
        :param variable: 绑定的数据变量
        :return: 输入框组件对象
        '''
        return customtkinter.CTkEntry(master, textvariable=variable)

    # 框架组件
    def frame_widget(self, master):
        '''
        框架组件
        :param master: 父组件
        :return: 框架组件对象
        '''
        return customtkinter.CTkFrame(master)

    # 可滚动框架组件
    def frame_scroll_widget(self, master):
        '''
        可滚动框架组件
        :param master: 父组件
        :return: 可滚动框架组件对象
        '''
        return customtkinter.CTkScrollableFrame(master)

    # 进度条组件
    def progressbar_widget(self, master, variable, mode=0):
        '''
        进度条组件
        :param master: 父组件
        :param variable: 绑定的数据变量
        :param orientation: 进度条方向，vertical（垂直），horizontal（水平）
        :return: 进度条组件对象
        '''
        if mode == 1:
            return customtkinter.CTkProgressBar(master, variable=variable, orientation="vertical")
        else:
            return customtkinter.CTkProgressBar(master, variable=variable, orientation="horizontal")

    # 组合框组件
    def combobox_widget(self, master, values: list, variable):
        '''
        组合框组件
        :param master: 父组件
        :param values: 选项列表
        :param variable: 绑定的数据变量
        :return: 组合框组件对象
        '''
        return customtkinter.CTkComboBox(master, values=values, variable=variable)

    # 分段组件
    def segmentedbutton_widget(self, master, values: list, variable):
        '''
        分段组件
        :param master: 父组件
        :param values: 选项列表
        :param variable: 绑定的数据变量
        :return: 分段组件对象
        '''
        return customtkinter.CTkSegmentedButton(master, values=values, variable=variable)

    # 单选按钮组件
    def radiobutton_widget(self, master, value, variable, textvariable):
        '''
        单选按钮组件
        :param master: 父组件
        :param value: 开启值
        :param variable: 绑定的数据变量
        :param textvariable: 组件的标题变量
        :return: 单选按钮组件对象
        '''
        return customtkinter.CTkRadioButton(master, value=value, variable=variable, textvariable=textvariable)

    # 多选框组件
    def checkbox_widget(self, master, onvalue, offvalue, variable, textvariable):
        '''
        多选框组件
        :param master: 父组件
        :param onvalue: 开启值
        :param offvalue: 关闭值
        :param variable: 绑定的数据变量
        :param textvariable: 组件的标题变量
        :return: 多选框组件对象
        '''
        return customtkinter.CTkCheckBox(master, onvalue=onvalue, offvalue=offvalue, variable=variable,
                                         textvariable=textvariable)

    # 开关组件
    def switch_widget(self, master, onvalue, offvalue, variable, textvariable):
        '''
        开关组件
        :param master: 父组件
        :param onvalue: 开启值
        :param offvalue: 关闭值
        :param variable: 绑定的数据变量
        :param textvariable: 组件的标题变量
        :return: 开关组件对象
        '''
        return customtkinter.CTkSwitch(master, onvalue=onvalue, offvalue=offvalue, variable=variable,
                                       textvariable=textvariable)

    # 滑块组件
    def slider_widget(self, master, from_, to_, variable):
        '''
        滑块组件
        :param master: 父组件
        :param from_: 最小值
        :param to_: 最大值值
        :param variable: 绑定的数据变量
        :param textvariable: 组件的标题变量
        :return: 滑块组件对象
        '''
        return customtkinter.CTkSlider(master, from_=from_, to=to_, variable=variable)

    # 选项菜单组件
    def optionmenu_widget(self, master, values: list, variable):
        '''
        选项菜单组件
        :param master: 父组件
        :param values: 选项列表
        :param variable: 绑定的数据变量
        :return: 选项菜单组件对象
        '''
        return customtkinter.CTkOptionMenu(master, values=values, variable=variable)

    # 选项卡组件
    def tab_widget(self, master):
        '''
        选项卡组件
        :param master: 父组件
        :return: 选项卡组件对象
        '''
        return customtkinter.CTkTabview(master)

    # 使用Treeview创建表格
    def treeview_table(self, master, headers: list, w_w, h_h, x_x, y_y, data: list = None, scollbar_mode: str = "y"):
        """
        使用Treeview创建表格
        :param master: 父组件
        :param headers: 表头列表
        :param w_w: 相对宽度，0-1
        :param h_h: 相对高度，0-1
        :param x_x: 相对x坐标，0-1
        :param y_y: 相对y坐标，0-1
        :param data: 表格数据，二维列表，每行数据为一个子列表，列表套列表[[]]
        :param scollbar_mode: 表格滚动条控制，x，y，xy
        :return: frame, tree, scrollbar_x, scrollbar_y对象
        """
        frame = self.frame_widget(master)
        frame.place(relwidth=w_w, relheight=h_h, relx=x_x, rely=y_y)
        # 创建Treeview组件
        tree = ttk.Treeview(frame, columns=headers, show="headings")

        # 设置表头
        for header in headers:
            tree.heading(header, text=header)
            # tree.column(header, width=len(header) * 20)
            tree.column(header, width=150, minwidth=len(header) * 20, anchor="center")

        # 插入数据
        if data is not None:
            for row in data:
                tree.insert("", "end", values=row)

        # 添加垂直滚动条
        scrollbar_x = None
        scrollbar_y = None
        rw = 1
        rh = 1
        if scollbar_mode == "y":
            scrollbar_y = customtkinter.CTkScrollbar(frame, orientation="vertical", command=tree.yview, width=10)
            tree.configure(yscrollcommand=scrollbar_y.set)
            scrollbar_y.pack(side="right", fill="y")
            frame.update()
            rw = (frame.winfo_width() - 10) / frame.winfo_width()

        elif scollbar_mode == "x":
            scrollbar_x = customtkinter.CTkScrollbar(frame, orientation="horizontal", command=tree.xview, height=10)
            tree.configure(xscrollcommand=scrollbar_x.set)
            scrollbar_x.pack(side="bottom", fill="x")
            frame.update()
            rh = (frame.winfo_height() - 10) / frame.winfo_height()

        elif scollbar_mode == "xy":
            scrollbar_y = customtkinter.CTkScrollbar(frame, orientation="vertical", command=tree.yview, width=10)
            tree.configure(yscrollcommand=scrollbar_y.set)
            y_rw = (frame.winfo_width() - 10) / frame.winfo_width()
            scrollbar_y.pack(side="right", fill="y")

            scrollbar_x = customtkinter.CTkScrollbar(frame, orientation="horizontal", command=tree.xview, height=10)
            tree.configure(xscrollcommand=scrollbar_x.set)
            scrollbar_x.pack(side="bottom", fill="x")

            frame.update()
            rw = (frame.winfo_width() - 10) / frame.winfo_width()
            rh = (frame.winfo_height() - 10) / frame.winfo_height()
        else:
            pass

        tree.place(relwidth=rw,
                   relheight=rh,
                   relx=0, rely=0)
        return frame, tree, scrollbar_x, scrollbar_y

    # 插入treeview表格数据
    def insert_treeview_table_data(self, master, data):
        '''
        插入数据
        :param master: tree对象
        :param data: 要插入的数据，是列表套列表形式
        :return:
        '''
        # 清空原有数据
        master.delete(*master.get_children())
        # 插入数据
        for row in data:
            master.insert("", "end", values=row)
